#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHM_FILE "./shmfile"
#define SHM_SIZE 4096
#define FIFO_FILE "./fifo"

int shmid= -1;
void *shmaddr = NULL;
char buf[300]={0};

void print_err(char *estr){
	perror(estr);
	exit(-1);
}
//创建共享内存
void create_or_get_shm(void){
	int fd =0;
	key_t key =-1;
	fd =open(SHM_FILE,O_RDWR|O_CREAT,0664);
	if(fd == -1) print_err("open fail");
	key = ftok(SHM_FILE,'b');
	if(key == -1) print_err("ftok fail");

	shmid=shmget(key,SHM_SIZE,0664|IPC_CREAT);
	if(shmid == -1) print_err("shmget err");

}

//共享内存写进程 通过管道来获取 共享内存读进程的进程id
int get_peer_pid(void){
	int ret =-1;
	int fifofd =-1;

	//创建有名管道文件
	ret =mkfifo(FIFO_FILE,0664);
	if(ret == -1 && errno != EEXIST) print_err("mkfifo err");
	printf("begin open fifo ....\n");
	//以只读方式打开管道
	fifofd = open(FIFO_FILE,O_RDONLY);//打开时阻塞
	if(fifofd == -1) print_err("open fifo fail");

	//读管道 获取"读共享内存进程" 的PID
	int peer_pid;
	printf("begin read fifo ....\n");
	ret = read(fifofd,&peer_pid,sizeof(peer_pid));
	if(ret ==-1) print_err("read fifo fail");
	printf("get peer_pid %d\n",peer_pid);
	return peer_pid;
}


void signal_fun(signum){
	if(SIGINT == signum){
		shmdt(shmaddr);
		shmctl(shmid,IPC_RMID,NULL);
		remove(SHM_FILE);
		remove(FIFO_FILE);
		exit(-1);
	}else if(SIGUSR1 == signum){
		printf("recv signum=%d\n",signum );
	}
	
}

//读共享进程的 把自己的pid写入管道 待写共享内存的进程读取
void snd_self_pid(void){
	int ret =-1;
	int fifofd =-1;

	//创建有名管道文件
	ret =mkfifo(FIFO_FILE,0664);
	if(ret == -1 && errno != EEXIST) print_err("mkfifo err");

	//以只写方式打开管道文件
	fifofd = open(FIFO_FILE,O_WRONLY);
	if(fifofd == -1) print_err("open fifo fail");

	//获取当前进程的pid,写入有名管道 待写共享内存的进程读取
	pid_t pid=getpid();
	ret = write(fifofd,&pid,sizeof(pid));

	if(ret ==-1) print_err("write fifo fail");

}